package com.zebra.remoting.tms;

import cn.hutool.core.thread.NamedThreadFactory;
import com.zebra.common.concurrent.ZebraExecutor;
import com.zebra.common.concurrent.ZebraExecutorGroup;
import com.zebra.remoting.config.ConfigManager;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Manager of processors<br>
 * Maintains the relationship between command and command processor through command code.
 * @author sk
 */
public class TmsExecutorManager {
    private static final InternalLogger logger = InternalLoggerFactory.getInstance(TmsExecutorManager.class);

    private static TmsExecutorManager poolManager = new TmsExecutorManager();

    /** The default executor, if no executor is set for processor, this one will be used */
    private ExecutorService                                      defaultExecutor;

    private ZebraExecutorGroup executorGroup;

    private int                                                  cpuSize    = ConfigManager
                                                                                    .default_ep_size();

    private int                                                  minPoolSize    = ConfigManager
                                                                                    .default_tp_min_size();

    private int                                                  maxPoolSize    = ConfigManager
                                                                                    .default_tp_max_size();

    private int                                                  queueSize      = ConfigManager
                                                                                    .default_tp_queue_size();

    private long                                                 keepAliveTime  = ConfigManager
                                                                                    .default_tp_keepalive_time();

    public static TmsExecutorManager getInstance() {
        if (null == poolManager) {
            poolManager = new TmsExecutorManager();
        }
        return poolManager;
    }

    private TmsExecutorManager() {
    }

    public void start(int minPoolSize){
        defaultExecutor = new ThreadPoolExecutor(minPoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(queueSize),
                new NamedThreadFactory("handler-executor", true));

        int num = Runtime.getRuntime().availableProcessors()  * cpuSize;
        num =  num < 64 ? 64 : num;
        executorGroup = new ZebraExecutorGroup(cpuSize, "handler-dis");
        executorGroup.start();
        logger.warn("Initialize executorGroup size {}", num);
    }

    public ZebraExecutor getDisruptorByLong(long userId){
        int index = (int) (userId % executorGroup.size());
        return executorGroup.getByIndex(index);
    }

    public ZebraExecutor getDisruptor(int no){
        return executorGroup.getByBizNo(no);
    }

    /**
     * Getter method for property <tt>defaultExecutor</tt>.
     * 
     * @return property value of defaultExecutor
     */
    public ExecutorService getDefaultExecutor() {
        return defaultExecutor;
    }

    /**
     * Set the default executor.
     * 
     * @param executor
     */
    public void registerDefaultExecutor(ExecutorService executor) {
        this.defaultExecutor = executor;
    }

}